﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using road2.Services;
using road2.Model;

namespace road2.code
{
    static class CarRoadManager
    {
        public static void PlaceCarToRoad(CarClass car, RoadClass road)
        {
            var r = GlobalRandomClass.Random;

            car.Road = road;
            car.Line = r.Next(0, road.LineCount);
            car.CurrentSpeed = r.Next(8, road.SpeedLimit + 1);
        }

        private static bool CheckLine(int line, CarClass car, IEnumerable<CarClass> cars)
        {
            if (line < 0 || line >= car.Road.LineCount) return false; // invalid line

            var nc = cars.NearestCarInFront(car.Distance, line);
            if (nc != null)
            {
                int delta = nc.Distance - 30 - car.Distance;
                if (delta < car.CurrentSpeed) // nearest car is close
                {
                    return false;
                }
            }

            return true; // road is empty or nearest car is far
        }

        public static void DriveCar(CarClass car, IEnumerable<CarClass> cars, IEnumerable<RoadClass> roads, IEnumerable<TrafficTerminatorClass> tts)
        {
            if (car.Road == null) return; // car dont on the road

            var carsOnRoad = cars.CarsOnRoad(car.Road).Except(new List<CarClass>() { car }); // all cars on the road except current car

            if (CheckLine(car.Line, car, carsOnRoad)) // check car's line
            {
                car.Drive();
            }
            else if (CheckLine(car.Line - 1, car, carsOnRoad)) // check left line
            {
                car.Line--;
                car.Drive();
            }
            else if (CheckLine(car.Line + 1, car, carsOnRoad)) // check right line
            {
                car.Line++;
                car.Drive();
            }
            else // fail to turn, slow down and follow nearest car
            {
                CarClass nc = carsOnRoad.NearestCarInFront(car.Distance, car.Line);
                car.CurrentSpeed = nc.CurrentSpeed;
                car.Drive(nc.Distance - 30 - car.Distance);
            }

            if (car.Distance > car.Road.Length) // end of road, try to drive on another road or tt
            {
                //car.Distance = car.Road.Length;
                //car.CurrentSpeed = 0;

                var tt = tts.Where(t => t.Road == car.Road);

                if (tt != null)
                {
                    tt.First().TermCar(car);
                }
            }
        }
    }
}
